iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 19
0
Software Development

python 自學系列 第 19

python day19 (Exceptions)

  • 分享至 

  • xImage
  •  

在執行程式時,可能會遇到一些問題導致程式執行失敗,這時候 python 就會丟出 exception,並且印出 stack trace,可以看是程式執行到哪邊發生錯誤.

>>> 1/0
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ZeroDivisionError: division by zero

如果執行的是一個檔案,會說是檔案哪一行錯了.

> python3 calc.py
5
6
8
Traceback (most recent call last):
  File "calc.py", line 4, in <module>
    print(1/0)
ZeroDivisionError: division by zero

寫程式時通常會有兩種方式來處理程式異常,一種就是先把會出現錯誤的情況避免掉也稱作 LBYL (look before you leap),另一種是就等發生了再來處理也稱作 EAFP (easier to ask for forgiveness than permission).

使用 LBYL 的話可以將上面的程式改成,用條件控制先判斷 num2 不為 0 才除,

>>> def division(num1,num2):
...  if num2 != 0:
...   print(num1 / num2)
...  else:
...   print(0)
...
>>> division(1,0)
0
>>> division(1,2)
0.5

可是假設將 None 丟進去,又會出錯了.所以使用 LBYL 的方式,需要考慮到很多情況來避免出錯.

>>> division(1,None)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in division
TypeError: unsupported operand type(s) for /: 'int' and 'NoneType'

使用 EAFP 的方式,將可能會出錯的地方放在 try 區塊裡,

>>> def division(num1,num2):
...  try:
...   print(num1 / num2)
...  except ZeroDivisionError as e:
...   print(0)
...
>>> division(1,0)
0
>>> division(1,2)
0.5
>>> division(1,None)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in division
TypeError: unsupported operand type(s) for /: 'int' and 'NoneType'

由於上面只有捕捉 ZeroDivisionError 的錯誤,所以如果不屬於該類型的錯誤,程式還是會執行錯誤,所以可以在下面再多一個比 ZeroDivisionError 層級更高的錯誤,就可以捕捉到.

>>> def division(num1,num2):
...  try:
...   print(num1 / num2)
...  except ZeroDivisionError as e:
...   print(0)
...  except Exception as e:
...   print('wrong number')
...
>>> division(1,None)
wrong number

raise & finally

如果補到例外後,想用不同的例外丟給呼叫該 function 的使用者,可以使用 raise 這關鍵字,像下面的範例捕捉到了 TypeError 會再把 RuntimeError 也拋出來給使用者.而 finally 區塊是不管有沒有發生例外,最後都會被執行的區塊.

>>> def division(num1,num2):
...  try:
...   print(num1 / num2)
...  except ZeroDivisionError as e:
...   print(0)
...  except Exception as e:
...   raise RuntimeError('wrong number')
...  finally:
...   print('do something...')
...
>>> division(1,2)
0.5
do something...
>>> division(1,0)
0
do something...
>>> division(1,None)
do something...
Traceback (most recent call last):
  File "<stdin>", line 3, in division
TypeError: unsupported operand type(s) for /: 'int' and 'NoneType'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 7, in division
RuntimeError: wrong number

自訂 exception

如果要定義自己的 exception,只需要將 class 繼承 Exception 即可.

>>> class CustomError(Exception):
...  pass
...

就可以使用了.

>>> def division(num1,num2):
...  try:
...   print(num1 / num2)
...  except ZeroDivisionError as e:
...   print(0)
...  except Exception as e:
...   raise CustomError('Custom wrong error')
...
>>> division(1,None)
Traceback (most recent call last):
  File "<stdin>", line 3, in division
TypeError: unsupported operand type(s) for /: 'int' and 'NoneType'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 7, in division
__main__.CustomError: Custom wrong error

上一篇
python day18 (Object Oriented Programming)
下一篇
python day20(csv、json)
系列文
python 自學30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言